package daili.cglib;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 动态代理：cglib
 * @author ben
 * @date 2021-10-20 16:36:01 CST
 */
public class SimpleCglibDemo {

	/**
	 * 被代理的类
	 * @author ben
	 * @date 2021-10-20 16:38:21 CST
	 */
	static class RealService {
		
		// 错误：无法被代理
//		private static AtomicInteger count;
//		public static AtomicInteger count;
		
		public String sayHello() {
			return "hello";
		}
		
		public Integer count(int count) {
			return count; 
		}
		
		// 调用后没有反应：cglib不支持 final方法
		public final String fm() {
			return "public final method";
		}
		
	}
	
	/**
	 * cglib: 方法拦截器
	 * @author ben
	 * @date 2021-10-20 16:42:07 CST
	 */
	static class SimpleInterceptor implements MethodInterceptor {

		@Override
		public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
			System.out.println("entering " + method.getName());
			
			// 错误：死循环
//			Object result = proxy.invoke(obj, args);
			// 正确！
			Object result = proxy.invokeSuper(obj, args);
			System.out.println("result=" + result);
			
			System.out.println("leaving " + method.getName());
			
			return result;
		}
		
	}
	
	/**
	 * cglib: 获取代理
	 * @author ben
	 * @date 2021-10-20 16:42:47 CST
	 * @param <T>
	 * @param cls 被代理的类
	 * @return
	 */
	private static <T> T getProxy(Class<T> cls) {
		Enhancer enhancer = new Enhancer();
		// 设置 父类（Super） 为 被代理类
		// 继承？
		enhancer.setSuperclass(cls);
		
		enhancer.setCallback(new SimpleInterceptor());
		
		return (T) enhancer.create();
	}
	
	public static void main(String[] args) {
		RealService proxyService = getProxy(RealService.class);
		proxyService.sayHello();
		proxyService.count(1);
		proxyService.count(2);
		
		// 调用 public final 方法：
		// 没有报错，也没有现实被调用
		// 直接调用了RealService的方法
		String fmret = proxyService.fm();
		System.out.println("fmtret=" + fmret);
		
		// 分析：调试用
//		analyzeProxyService(proxyService);
	}

	/**
	 * 分析代理得到对象
	 * @author ben
	 * @date 2021-10-20 16:54:22 CST
	 * @param proxyService
	 */
	private static void analyzeProxyService(RealService proxyService) {
		System.out.println("分析proxyService：");
		Class<?> cls = proxyService.getClass();
		System.out.println(cls);
		System.out.println(cls.getName());
		System.out.println(cls.getSimpleName());
		System.out.println(cls.getCanonicalName());
		
		// 所有public方法，包括其父类
//		Method[] mtds = cls.getMethods();
		// 本类声明的所有方法，包括非public的，但不包括父类的
		Method[] mtds = cls.getDeclaredMethods();
		System.out.println("方法数量：mtds.length=" + mtds.length);
		Arrays.asList(mtds).forEach(mtd->{
			System.out.println("\n方法：" + mtd.getName());
			System.out.println(mtd);
			
			final int mod = mtd.getModifiers();
			System.out.println("modifieres: " + mod);
			System.out.println("isAbstract=" + Modifier.isAbstract(mod));
			System.out.println("isFinal=" + Modifier.isFinal(mod));
			System.out.println("isNative=" + Modifier.isNative(mod));
			System.out.println("isPrivate=" + Modifier.isPrivate(mod));
			System.out.println("isPublic=" + Modifier.isPublic(mod));
			System.out.println("isStrict=" + Modifier.isStrict(mod));
			System.out.println("isStatic=" + Modifier.isStatic(mod));
			System.out.println("isSynchronized=" + Modifier.isSynchronized(mod));
			System.out.println("isTransient=" + Modifier.isTransient(mod));
			System.out.println("isVolatile=" + Modifier.isVolatile(mod));
		});
	}

}
